﻿namespace PasswordGenerator.Generator
{
    using System;
    using System.Security.Cryptography;

    public class RngCryptoProvider : ICryptoProvider
    {
        private readonly RandomNumberGenerator randomNumGen;

        private readonly byte[] randomBytes;

        public RngCryptoProvider()
        {
            this.randomNumGen = RNGCryptoServiceProvider.Create();
            this.randomBytes = new byte[4];
        }

        public uint GetNext(uint minValue, uint maxValue)
        {
            this.randomNumGen.GetBytes(this.randomBytes);

            var randomNumber = (uint)randomBytes[0] * 1u +
                               (uint)randomBytes[0] * 256u +
                               (uint)randomBytes[0] * 65536u +
                               (uint)randomBytes[0] * 16777216u;

            return this.NormalizeValueRng(randomNumber, minValue, maxValue);
        }

        private uint NormalizeValueRng(uint randomValue, uint minValue, uint maxValue)
        {
            if (minValue >= maxValue)
            {
                throw new InvalidOperationException("maxValue must be bigger than minValue!");
            }

            uint characterCount = maxValue - minValue;

            return (uint)((double)randomValue / (double)uint.MaxValue * (double)characterCount - 1.0d + 0.5d) + minValue;
        }
    }
}
